package com.ark.common.config;

import com.ark.common.domain.entity.game.GameInfo;
import com.ark.common.mybatis.interceptor.DataPermissionInterceptor;
import com.ark.common.mybatis.permission.DataPermissionRule;
import com.ark.common.mybatis.permission.DataPermissionRuleCustomizer;
import com.ark.common.utils.MyBatisUtils;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import net.sf.jsqlparser.statement.select.Select;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import java.util.List;


@Configuration
@EnableTransactionManagement(proxyTargetClass = true)
public class MybatisPlusConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        // 自定义数据权限插件，因为该拦截器需要注入其他bean，所以无法在这里配置到拦截器中，会报循环依赖，无法启动
        // interceptor.addInnerInterceptor(new DataPermissionInterceptor(rule));
        // 分页插件
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        return interceptor;
    }
    /**
     * 为什么不直接配置到上面的拦截器中呢？因为拦截器中给自定义拦截器注入bean会报相互依赖，无法启动
     */
    @Bean
    public DataPermissionInterceptor dataPermissionDatabaseInterceptor(MybatisPlusInterceptor interceptor,
                                                                       DataPermissionRule ruleFactory) {
        // 创建 DataPermissionInterceptor 拦截器
        DataPermissionInterceptor inner = new DataPermissionInterceptor(ruleFactory);
        // 添加到 interceptor 中
        // 需要加在首个，主要是为了在分页插件前面。这个是 MyBatis Plus 的规定
        MyBatisUtils.addInterceptor(interceptor, inner, 0);
        return inner;
    }

    /**
     * 配置数据权限规则 ，通过spring自动注入收集所有对表名，字段名的配置类，创建规则配置类rule，循环调用 DataPermissionRuleCustomizer 设置rule属性收集权限控制的表名和字段名
     */
    @Bean
    public DataPermissionRule dataPermissionRule(List<DataPermissionRuleCustomizer> customizers, RoleHierarchy roleHierarchy) {
        // 创建 DataPermissionRule 对象
        DataPermissionRule rule = new DataPermissionRule(roleHierarchy);
        // 补全表配置
        customizers.forEach(customizer -> customizer.customize(rule));
        return rule;
    }


    /**
     * 实现对权限的真正配置，添加需要拦截的表名，字段名。因为在${@link DataPermissionInterceptor#processSelect(Select, int, String, Object)}做了判断
     * 只有配置了拦截的表名，才会进行拦截，否则默认都拦截
     */
    @Bean
    public DataPermissionRuleCustomizer dataPermissionRuleCustomizer() {
        return rule -> {
            //rule.addUserColumn(SysMenu.class);
            rule.addUserColumn(GameInfo.class);//商户是这个类？不是，这个是游戏账号的类
            // 添加需要拦截的表对应的DO类，表必须拥有user_id 和 agent_id 两个字段
        };
    }
}
